﻿using Century.EnterpriseLibrary.Configuration;
///***************************************
///Developed by Farshid Mirzagholi
///***************************************
using System;
using System.Collections.Generic;


namespace Century.EnterpriseLibrary.Caching
{
    public static class CacheService //: ICacheService
    {
        //public static readonly CacheService Instance = new CacheService();

        private static readonly object CacheLockObject = new object();
        //private ILogService log;
        private static bool CachingEnabled
        {
            get
            {
                //ToDo: you can read from config if cache is enable or not
                return true;
            }
        }
        //private CacheService()
        //{

        //}

        private static ICacheManager GetCacheManager
        {
            get
            {
                switch (ConfManager.Instance.CacheManager.ActiveCache)
                {
                    case "CouchBase":
                        return CouchbaseDB.Instance;
                    case "MemoryCache":
                        return MemoryCacheManager.Instance;
                    default:
                        return MemoryCacheManager.Instance;
                }
            }
        }

        public static void Add(string cacheKey, object data)
        {
            if (!CachingEnabled)
            {
                return;
            }

            try
            {
                //Default Cache Time 1 hour
                TimeSpan expiration = new TimeSpan(1, 0, 0);
                GetCacheManager.Set(cacheKey, data, expiration);
            }
            catch (Exception exc)
            {
                //Log(exc, cacheKey);
            }
        }

        public static void Add(string cacheKey, object data, TimeSpan expiration)
        {
            if (!CachingEnabled)
            {
                return;
            }

            try
            {
                GetCacheManager.Set(cacheKey, data, expiration);
            }
            catch (Exception exc)
            {
                //Log(exc, cacheKey);
            }
        }

        public static void Remove(string cacheKey)
        {
            if (!CachingEnabled)
            {
                return;
            }

            try
            {
                GetCacheManager.Remove(cacheKey);

            }
            catch (Exception exc)
            {
                //Log(exc, cacheKey);
            }
        }

        public static object Get<T>(string cacheKey)
        {
            if (!CachingEnabled)
            {
                return null;
            }
            try
            {
                object data = GetCacheManager.Get<T>(cacheKey);
                return data;
            }
            catch (Exception exc)
            {
                //Log(exc, cacheKey);
            }

            return null;
        }

        public static object Get<T>(string cacheKey, Func<object> getData)
        {
            if (!CachingEnabled)
            {
                return getData();
            }
            try
            {
                object data = Get<T>(cacheKey);
                if (data == null)
                {
                    lock (CacheLockObject)
                    {
                        if (data == null)
                        {
                            data = getData();

                            Add(cacheKey, data);
                        }
                    }
                }

                return data;
            }
            catch (Exception exc)
            {
                //Log(exc, cacheKey);
            }

            return null;
        }

        public static T Get<T>(string cacheKey, Func<T> getData)
            where T : class
        {
            if (!CachingEnabled)
            {
                return getData() as T;
            }

            try
            {
                object data = Get<T>(cacheKey);
                if (data == null)
                {
                    lock (CacheLockObject)
                    {
                        if (data == null)
                        {
                            data = getData();
                            if (data != null)
                            {
                                Add(cacheKey, data);
                            }
                        }
                    }
                }

                return data as T;
            }
            catch (Exception exc)
            {
                //Log(exc, cacheKey);
            }

            return null;
        }

        public static T Get<T>(string cacheKey, Func<T> getData, TimeSpan expiration)
            where T : class
        {
            if (!CachingEnabled)
            {
                return getData();
            }

            try
            {
                object data = Get<T>(cacheKey);
                if (data == null)
                {
                    lock (CacheLockObject)
                    {
                        if (data == null)
                        {
                            data = getData();

                            Add(cacheKey, data, expiration);
                        }
                    }
                }

                return data as T;
            }
            catch (Exception exc)
            {
                //Log(exc, cacheKey);
            }

            return null;
        }

        public static object Get<T>(string cacheKey, Func<object> getData, TimeSpan expiration)
        {
            if (!CachingEnabled)
            {
                return getData();
            }
            try
            {
                object data = Get<T>(cacheKey);
                if (data == null)
                {
                    lock (CacheLockObject)
                    {
                        if (data == null)
                        {
                            data = getData();

                            Add(cacheKey, data, expiration);
                        }
                    }
                }

                return data;
            }
            catch (Exception exc)
            {
                //Log(exc, cacheKey);
            }

            return null;
        }

    }


}
